package com.fengye.common.resolver;

import com.fengye.common.annotation.CurrentUserId;
import com.fengye.common.constants.AppHttpCodeEnum;
import com.fengye.common.constants.CommonConstant;
import com.fengye.common.exception.BusinessException;
import com.fengye.common.utils.JwtUtil;
import com.fengye.common.utils.StringUtils;
import com.fengye.common.utils.TokenExtractorUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import jakarta.servlet.http.HttpServletRequest;

/**
 * @author sunlei
 * @version 1.0
 * @date 2023/12/6 09:08:48
 * @description 自定义controller中方法的参数解析器，解析header中token中的userid，
 * 这样就不需要在controller中的很多handler方法中一遍遍写解析token的模版代码了
 */
@Slf4j
public class MyHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    // 是否使用当前参数解析器
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 如果方法的参数的前加上了@CurrentUserId注解，就使用我们自定义的解析器解析
        return parameter.hasParameterAnnotation(CurrentUserId.class);
    }

    // 解析参数，并将解析的数据赋值到handler方法上指定的参数上
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        // 获取请求头中的token
        String token = TokenExtractorUtils.getHeaderBearerToken(request);
        if (StringUtils.isNotBlank(token)) {
            try {
                String userId = JwtUtil.parseUserId(token);
                return Long.valueOf(userId);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("resolveArgument: 解析token失败");
                throw new BusinessException(AppHttpCodeEnum.TOKEN_INVALID);
            }
        } else {
            log.error("resolveArgument: token不能为空");
            throw new BusinessException(AppHttpCodeEnum.UNAUTHORIZED);
        }
    }
}
